/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lauglog.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Vector;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lauglog.util.Day;
import java.sql.*;
import lauglog.bean.EventBean;
import lauglog.bean.UserBean;
import lauglog.util.CompletedEvent;
import org.joda.time.DateTime;
import org.joda.time.Days;

/**
 * This class does all processing for the calendar page
 * It generates a json object representing all the 
 * plan and event information for a specific month and
 * sends this back to the requesting page
 * 
 * 
 * @author Waseem Mir
 */
@WebServlet(name = "CalendarServlet", urlPatterns = {"/CalendarServlet"})
public class CalendarServlet extends HttpServlet {
    
    //instance variables to represent various dates that are 
    //important to constructing the calendar json object
    
    //this gets today day
    private int todaysDOM; 
    
    //todays month
    private int todaysMonth;
    
    //todays year
    private int todaysYear;
    
    //get the day of week of the first of the month the user is viewing
    private int firstOfMonthDOW;
    
    //get the last day of the month which the user is viewing
    private int lastOfMonth;
    
    //the printwriter to write out the json object
    private PrintWriter out;
    
    //an array of month names in order
    private final String [] months = new String []{"January","February","March","April","May","June","July","August","September","October","November","December"};

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("application/json");
        out = response.getWriter();
        
        //get the query string parameters
        //representing the month the user is looking at
        //and the plan that the user wants to view
        //the default action is to generate a simple calendar
        //for the current month (before the user has even
        //selected a plan to view)
        int year = Integer.parseInt(request.getParameter("year"));
        int month = Integer.parseInt(request.getParameter("month"));
        int planId = Integer.parseInt(request.getParameter("planId"));
        
        //get reference to users id
        int userId = ((UserBean)(request.getSession().getAttribute("user"))).getUserID();
        
        //set todays day, month, year
        /******************IMPORTANT! remember that java starts at Sunday=1, DOM=1,DOW=1,Jan=0!!************/
        Calendar today = new GregorianCalendar();
        todaysDOM = today.get(Calendar.DAY_OF_MONTH);
        todaysMonth = today.get(Calendar.MONTH)+1;
        todaysYear = today.get(Calendar.YEAR);
        Calendar FOM = new GregorianCalendar(todaysYear,todaysMonth-1,1);
        firstOfMonthDOW = FOM.get(Calendar.DAY_OF_WEEK);
        lastOfMonth = today.getActualMaximum(Calendar.DAY_OF_MONTH);
        
        
        //if user is viewing the present month and planId not set
        //go to the set up the simple calendar method
        if (year == todaysYear && month == todaysMonth)
            if (planId<0)
                simpleCalendar();
        
        //else if user is viewing present month and planId is set
        //go to the set up present day plans
            else 
                presentCalendar(planId,userId);
        
        //else its a day in the past, set up the past calendars
        else
            pastCalendar(month,year,planId,userId);
    }
    
    private void simpleCalendar()
    {
        //a list of day objects to represent days
        //on a 42 day calendar
        Vector<Day> calendar = new Vector<Day>();
        
        //counter to keep track of the actual days of the month
        int dayCounter = 1;
        
        //fill up the list appropriately
        for (int i=1; i<43; i++)
        {
            //a single day object
            Day tempDay;
            
            //make sure to only fill out those days
            //that will actually have dates
            if(i<firstOfMonthDOW || i>(lastOfMonth+firstOfMonthDOW-1))
                tempDay = new Day(-1,null);
            else
            {
                tempDay = new Day(dayCounter,null);
                dayCounter++;
            }
            
            calendar.add(tempDay);
        }
        
        //call the method to turn the list into a JSON object
        makeJsonObject(calendar);
    
    }
    
    private void presentCalendar(int planId,  int userId)
    {
        
        //the offset of the plan start(join) date relative to the first of the month
        int planStartOffset;
        
        //the duration of the plan
        int duration;
        
        //the offset of the plan end date relative to the first of the month
        int planEndOffset;
        
        //make the database call to get the specific plan and check if it 
        //is even visible within the viewable month
        //Initiate variables for database queries
        String url = "jdbc:mysql://localhost/lauglog";
        String dbUserName = "root";
        String dbPassword = "";
        String driver = "com.mysql.jdbc.Driver";
        Connection con = null;
        
        try{
            
            //Make the connection
            Class.forName(driver).newInstance();
            con = DriverManager.getConnection(url, dbUserName, dbPassword);
            
            //Query db for the specific plan from joined plans table
            //returning the start date as a date, and the duration in days
            PreparedStatement planRangeStatement = con.prepareStatement("SELECT DATE(StartDate) AS StartDate,Duration FROM joined_plans WHERE PlanId = ? AND UserId = ?");
            planRangeStatement.setInt(1, planId);
            planRangeStatement.setInt(2, userId);
            ResultSet planRangeRs = planRangeStatement.executeQuery();
            planRangeRs.first();
            
            //retreive the start date
            java.sql.Date startDate = planRangeRs.getDate("StartDate");            
            
            //retreive the duration
            duration = planRangeRs.getInt("Duration");
            
            
            //convert date to java date object
            java.util.Date jStartDate = new java.util.Date(startDate.getTime());
            
            //convert date object to calendar
            Calendar realStartDate = new GregorianCalendar();
            realStartDate.setTime(jStartDate);
            
            //Create a Calendar object representing the first of the viewable month
            Calendar firstOfMonth = new GregorianCalendar(todaysYear,todaysMonth-1,1);
            
            //get the days between the start of the plan and the first of this month
            //uses the joda time library
            planStartOffset = Days.daysBetween(new DateTime(firstOfMonth), new DateTime(realStartDate)).getDays();
            
            System.out.print("sOffset: "+planStartOffset);
            
            //set the offset of the end of plan
            planEndOffset = planStartOffset+duration-1;
            
            //if the start date exceeds the end of this month, or the end is before the first, just make a simple calendar
            if (planStartOffset >= lastOfMonth || planEndOffset<0)
                simpleCalendar();
            
            //else continue making the calendar
            else
            {
                //list of all events associated with the selected plan
                Vector<EventBean> plannedEvents = new Vector<EventBean>();
                
                //db query to get all these events
                PreparedStatement plannedEventsStatement = con.prepareStatement("SELECT Name,Type,RepeatRate,DayOfWeek FROM events WHERE PlanId = ?");
                plannedEventsStatement.setInt(1,planId);
                ResultSet plannedEventsRs = plannedEventsStatement.executeQuery();
                
                //create events one by one and add to list of events
                while(plannedEventsRs.next())
                {
                    EventBean tempEvent = new EventBean();
                    boolean [] daysOfWeekBools = {false,false,false,false,false,false,false};
                    String daysOfWeek = "";
                    
                    tempEvent.setEventName(plannedEventsRs.getString("Name"));
                    tempEvent.setEventType(plannedEventsRs.getString("Type"));
                    tempEvent.setRepeatNumber(plannedEventsRs.getInt("RepeatRate"));
                    daysOfWeek = plannedEventsRs.getString("DayOfWeek");
                    
                    //set days of the week boolean array
                    for(int i=0; i<daysOfWeek.length(); i++)
                    {
                        char day = daysOfWeek.charAt(i);
                        switch(day) {
                            case 'M': daysOfWeekBools[1] = true;
                                      break;
                            case 'T': daysOfWeekBools[2] = true;
                                      break;
                            case 'W': daysOfWeekBools[3] = true;
                                      break;
                            case 'H': daysOfWeekBools[4] = true;
                                      break;
                            case 'F': daysOfWeekBools[5] = true;
                                      break;
                            case 'S': daysOfWeekBools[6] = true;
                                      break;
                            case 'U': daysOfWeekBools[0] = true;
                                      break;
                                
                        }
                    }
                    
                    tempEvent.setDaysOfWeek(daysOfWeekBools);
                    
                    //add the new event bean to the list of events
                    plannedEvents.add(tempEvent);
                }
                
                //Now we need to get all the events that have been completed in the viewable timeframe
                //lists of the different types of events
                Vector<CompletedEvent> completedMetricEvents = new Vector<CompletedEvent>();
                Vector<CompletedEvent> completedStaticEvents = new Vector<CompletedEvent>();
                Vector<CompletedEvent> completedBpEvents = new Vector<CompletedEvent>();
                
                //Make the lists using separate queries
                
                //String to represent todays date in MySQL format
                String today = "'"+todaysYear+"-"+todaysMonth+"-"+1+"'";
                System.out.print(today);
                
                //metric first
                PreparedStatement completedMetricEventsStatement = con.prepareStatement("SELECT E.Name,M.RecordedValue,DATE(DateTime) AS DateTime FROM events E, metric_data M WHERE PlanId = ? AND E.EventId=M.EventId AND DATE(DateTime) <= CURDATE() AND DATE(DateTime)>=? AND M.UserId = ?");
                completedMetricEventsStatement.setInt(1,planId);
                completedMetricEventsStatement.setString(2,today);
                completedMetricEventsStatement.setInt(3,userId);
                ResultSet completedMetricEventsRs = completedMetricEventsStatement.executeQuery();
                
                //convert result set of query into list of completed metric events
                while(completedMetricEventsRs.next())
                {
                    System.out.print("before first loop");
                    CompletedEvent temp = new CompletedEvent();
                    temp.setEventName(completedMetricEventsRs.getString("Name"));
                    int recordedValue = completedMetricEventsRs.getInt("RecordedValue");
                    if (recordedValue<0)
                        temp.setCompleted(-1);
                    else
                        temp.setCompleted(1);
                    
                    java.sql.Date eventDate = completedMetricEventsRs.getDate("DateTime");
                    java.util.Date jeventDate = new java.util.Date(eventDate.getTime());
                    Calendar realEventDate = new GregorianCalendar();
                    realEventDate.setTime(jeventDate);
                    
                    //get the offset between the first and the event (add 1 to get a day of month)
                    int offset = Days.daysBetween(new DateTime(firstOfMonth), new DateTime(realEventDate)).getDays();
                    temp.setDate(offset+1);
                    
                    //add this event object to the list of metric events
                    completedMetricEvents.add(temp);
                    System.out.print("after first loop");
                }
                
                //static events next
                PreparedStatement completedStaticEventsStatement = con.prepareStatement("SELECT E.Name,S.Completed,DATE(DateTime) AS DateTime FROM events E, static_data S WHERE PlanId = ? AND E.EventId=S.EventId AND DATE(DateTime) <= CURDATE() AND DATE(DateTime)>=? AND S.UserId=?");
                completedStaticEventsStatement.setInt(1,planId);
                completedStaticEventsStatement.setString(2,today);
                completedStaticEventsStatement.setInt(3,userId);
                ResultSet completedStaticEventsRs = completedStaticEventsStatement.executeQuery();
                
                //convert result set of query into list of completed static events
                while(completedStaticEventsRs.next())
                {
                    CompletedEvent temp = new CompletedEvent();
                    temp.setEventName(completedStaticEventsRs.getString("Name"));
                    int completed = completedStaticEventsRs.getInt("Completed");
                    if (completed>0)
                        temp.setCompleted(1);
                    else
                        temp.setCompleted(-1);
                    
                    java.sql.Date eventDate = completedStaticEventsRs.getDate("DateTime");
                    java.util.Date jeventDate = new java.util.Date(eventDate.getTime());
                    Calendar realEventDate = new GregorianCalendar();
                    realEventDate.setTime(jeventDate);
                    
                    //get the offset between the first and the event (add 1 to get a day of month)
                    int offset = Days.daysBetween(new DateTime(firstOfMonth), new DateTime(realEventDate)).getDays();
                    temp.setDate(offset+1);
                    
                    //add this event object to the list of metric events
                    completedStaticEvents.add(temp);
                }
                System.out.print("after second loop");
                
                //bp events next
                PreparedStatement completedBpEventsStatement = con.prepareStatement("SELECT E.Name,B.Systolic,DATE(DateTime) FROM events E, bp_data B WHERE PlanId = ? AND E.EventId=B.EventId AND DATE(DateTime) <= CURDATE() AND DATE(DateTime)>=? AND B.UserId=?");
                completedBpEventsStatement.setInt(1,planId);
                completedBpEventsStatement.setString(2,today);
                completedBpEventsStatement.setInt(3,userId);
                ResultSet completedBpEventsRs = completedBpEventsStatement.executeQuery();
                
                //convert result set of query into list of completed bp events
                while(completedBpEventsRs.next())
                {
                    CompletedEvent temp = new CompletedEvent();
                    temp.setEventName(completedBpEventsRs.getString("Name"));
                    int systolic = completedBpEventsRs.getInt("Systolic");
                    if (systolic<0)
                        temp.setCompleted(-1);
                    else
                        temp.setCompleted(1);
                    
                    java.sql.Date eventDate = completedBpEventsRs.getDate("DateTime");
                    java.util.Date jeventDate = new java.util.Date(eventDate.getTime());
                    Calendar realEventDate = new GregorianCalendar();
                    realEventDate.setTime(jeventDate);
                    
                    //get the offset between the first and the event (add 1 to get a day of month)
                    int offset = Days.daysBetween(new DateTime(firstOfMonth), new DateTime(realEventDate)).getDays();
                    temp.setDate(offset+1);
                    
                    //add this event object to the list of metric events
                    completedBpEvents.add(temp);
                }
                System.out.print("after second loop");
                
                //now we need to convert all this data into an array of Day objects
                //which can be more easily used to make the json object to return
                
                //a list of day objects to represent days
                //on a 42 day calendar
                Vector<Day> calendar = new Vector<Day>();

                //counter to keep track of the actual days of the month
                int dayCounter = 1;

                //fill up the list appropriately
                for (int i=1; i<43; i++)
                {
                    System.out.println(i);
                    //a single day object
                    Day tempDay;

                    //make sure to only fill out those days
                    //that will actually have dates
                    if(i<firstOfMonthDOW || i>(lastOfMonth+firstOfMonthDOW-1))
                        tempDay = new Day(-1,null);
                    else
                    {
                        //construct the list of events that will go in the day object
                        Vector<CompletedEvent> tempEventList = new Vector<CompletedEvent>();
                        
                        //if the current constructed day is in the past, then use
                        //the list of completed events to construct the events list
                        if (dayCounter<todaysDOM)
                        {
                            //completed metric events
                            for(int j=0;j<completedMetricEvents.size(); j++)
                            {
                                if(completedMetricEvents.get(j).getDate()==dayCounter)
                                {
                                    CompletedEvent tempEvent = new CompletedEvent();
                                    tempEvent.setEventName(completedMetricEvents.get(j).getEventName());
                                    tempEvent.setEventType("metric");
                                    tempEvent.setCompleted(completedMetricEvents.get(j).getCompleted());
                                    tempEvent.setDate(dayCounter);
                                    tempEventList.add(tempEvent);
                                }
                            }
                            
                            //completed static events
                            for(int j=0;j<completedStaticEvents.size(); j++)
                            {
                                if(completedStaticEvents.get(j).getDate()==dayCounter)
                                {
                                    CompletedEvent tempEvent = new CompletedEvent();
                                    tempEvent.setEventName(completedStaticEvents.get(j).getEventName());
                                    tempEvent.setEventType("static");
                                    tempEvent.setCompleted(completedStaticEvents.get(j).getCompleted());
                                    tempEvent.setDate(dayCounter);
                                    tempEventList.add(tempEvent);
                                }
                            }
                            
                            //completed bp events
                            for(int j=0;j<completedBpEvents.size(); j++)
                            {
                                if(completedBpEvents.get(j).getDate()==dayCounter)
                                {
                                    CompletedEvent tempEvent = new CompletedEvent();
                                    tempEvent.setEventName(completedBpEvents.get(j).getEventName());
                                    tempEvent.setEventType("bp");
                                    tempEvent.setCompleted(completedBpEvents.get(j).getCompleted());
                                    tempEvent.setDate(dayCounter);
                                    tempEventList.add(tempEvent);
                                }
                            }
                            
                            //now add the rest of the information for the day
                            tempDay = new Day(dayCounter,tempEventList);
                            dayCounter++;
                        }
                        
                        //if the day object being constructed is for today then
                        //we need to pull from completedEvents list and future events
                        else if (dayCounter==todaysDOM)
                        {
                            //completed metric events
                            for(int j=0;j<completedMetricEvents.size(); j++)
                            {
                                if(completedMetricEvents.get(j).getDate()==dayCounter)
                                {
                                    CompletedEvent tempEvent = new CompletedEvent();
                                    tempEvent.setEventName(completedMetricEvents.get(j).getEventName());
                                    tempEvent.setEventType("metric");
                                    tempEvent.setCompleted(completedMetricEvents.get(j).getCompleted());
                                    tempEvent.setDate(dayCounter);
                                    tempEventList.add(tempEvent);
                                }
                            }
                            
                            //completed static events
                            for(int j=0;j<completedStaticEvents.size(); j++)
                            {
                                if(completedStaticEvents.get(j).getDate()==dayCounter)
                                {
                                    CompletedEvent tempEvent = new CompletedEvent();
                                    tempEvent.setEventName(completedStaticEvents.get(j).getEventName());
                                    tempEvent.setEventType("static");
                                    tempEvent.setCompleted(completedStaticEvents.get(j).getCompleted());
                                    tempEvent.setDate(dayCounter);
                                    tempEventList.add(tempEvent);
                                }
                            }
                            
                            //completed bp events
                            for(int j=0;j<completedBpEvents.size(); j++)
                            {
                                if(completedBpEvents.get(j).getDate()==dayCounter)
                                {
                                    CompletedEvent tempEvent = new CompletedEvent();
                                    tempEvent.setEventName(completedBpEvents.get(j).getEventName());
                                    tempEvent.setEventType("bp");
                                    tempEvent.setCompleted(completedBpEvents.get(j).getCompleted());
                                    tempEvent.setDate(dayCounter);
                                    tempEventList.add(tempEvent);
                                }
                            }
                            
                            //keep constructing from list of planned Events
                            
                            //Get the day of the week of the day being constructed
                            System.out.println(todaysYear);
                            System.out.println(todaysMonth);
                            System.out.println(dayCounter);
                            Calendar tempDate = new GregorianCalendar(todaysYear,todaysMonth-1,dayCounter);
                            int tempDayOfWeek = tempDate.get(Calendar.DAY_OF_WEEK);
                            
                            
                            System.out.print("dayOfweek: "+tempDayOfWeek);
                            
                            for(int j=0;j<plannedEvents.size();j++)
                            {
                                if(plannedEvents.get(j).getDaysOfWeek()[tempDayOfWeek-1] && dayCounter>planStartOffset && dayCounter<=(planEndOffset+1))
                                {   
                                    //variable used to count the number of weeks
                                    //since the plan start date (8 days since 
                                    //start of plan = 2nd week)
                                    
                                    //days between current day and plan start
                                    int weekCheck = dayCounter-planStartOffset+1;
                                    
                                    //the actual week we are in
                                    weekCheck = (weekCheck/7) + 1;
                                    System.out.print("week : "+weekCheck);
                                    
                                    if((weekCheck-1) % plannedEvents.get(j).getRepeatNumber() == 0)
                                    {
                                        CompletedEvent tempEvent = new CompletedEvent();
                                        tempEvent.setEventName(plannedEvents.get(j).getEventName());
                                        tempEvent.setEventType(plannedEvents.get(j).getEventType());
                                        tempEvent.setCompleted(0);
                                        tempEvent.setDate(dayCounter);
                                        tempEventList.add(tempEvent);
                                    }
                                }
                            }
                            
                            //now add the rest of the information for the day
                            tempDay = new Day(dayCounter,tempEventList);
                            dayCounter++;
                        }
                        
                        //a day in the future will be constructed using only the
                        //planned events list
                        else
                        {
                            //Get the day of the week of the day being constructed
                            Calendar tempDate = new GregorianCalendar(todaysYear,todaysMonth-1,dayCounter);
                            int tempDayOfWeek = tempDate.get(Calendar.DAY_OF_WEEK);
                            
                            for(int j=0;j<plannedEvents.size();j++)
                            {
                                if(plannedEvents.get(j).getDaysOfWeek()[tempDayOfWeek-1] && dayCounter>planStartOffset && dayCounter<=(planEndOffset+1))
                                {   
                                    //variable used to count the number of weeks
                                    //since the plan start date (8 days since 
                                    //start of plan = 2nd week)
                                    
                                    //days between current day and plan start
                                    int weekCheck = dayCounter-planStartOffset+1;
                                    
                                    //the actual week we are in
                                    weekCheck = (weekCheck/7) + 1;
                                    System.out.print("week : "+weekCheck);
                                    
                                    if((weekCheck-1) % plannedEvents.get(j).getRepeatNumber() == 0)
                                    {
                                        CompletedEvent tempEvent = new CompletedEvent();
                                        tempEvent.setEventName(plannedEvents.get(j).getEventName());
                                        tempEvent.setEventType(plannedEvents.get(j).getEventType());
                                        tempEvent.setCompleted(0);
                                        tempEvent.setDate(dayCounter);
                                        tempEventList.add(tempEvent);
                                    }
                                }
                            }
                            
                            //now add the rest of the information for the day
                            tempDay = new Day(dayCounter,tempEventList);
                            dayCounter++;
                        }
                    }

                    calendar.add(tempDay);
                }

                //call the method to turn the list into a JSON object
                makeJsonObject(calendar);
            }         
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try{
                con.close();
            }catch(Exception e){
                
            }
        }

        
    }
    
    private void pastCalendar(int month, int year, int planId, int userId)
    {
        //set todays day, month, year for specific month in the past (by default, use first of that month)
        /******************IMPORTANT! remember that java starts at Sunday=1, DOM=1,DOW=1,Jan=0!!************/
        Calendar past = new GregorianCalendar(year,month-1,1);
        todaysDOM = 1;
        firstOfMonthDOW = past.get(Calendar.DAY_OF_WEEK);
        lastOfMonth = past.getActualMaximum(Calendar.DAY_OF_MONTH);
        todaysYear = year;
        todaysMonth = month;
        
        //if plan id isn't set we make a simple calendar with the new variables
        if (planId<0)
            simpleCalendar();
        
        //else make a past calendar
        else
        {
            //the offset of the plan start(join) date relative to the first of the month
            int planStartOffset;

            //the duration of the plan
            int duration;

            //the offset of the plan end date relative to the first of the month
            int planEndOffset;

            //make the database call to get the specific plan and check if it 
            //is even visible within the viewable month
            //Initiate variables for database queries
            String url = "jdbc:mysql://localhost/lauglog";
            String dbUserName = "root";
            String dbPassword = "";
            String driver = "com.mysql.jdbc.Driver";
            Connection con = null;

            try{

                //Make the connection
                Class.forName(driver).newInstance();
                con = DriverManager.getConnection(url, dbUserName, dbPassword);

                //Query db for the specific plan from joined plans table
                //returning the start date as a date, and the duration in days
                PreparedStatement planRangeStatement = con.prepareStatement("SELECT DATE(StartDate) AS StartDate,Duration FROM joined_plans WHERE PlanId = ? AND UserId=?");
                planRangeStatement.setInt(1, planId);
                planRangeStatement.setInt(2, userId);
                ResultSet planRangeRs = planRangeStatement.executeQuery();
                planRangeRs.first();

                //retreive the start date
                java.sql.Date startDate = planRangeRs.getDate("StartDate");            

                //retreive the duration
                duration = planRangeRs.getInt("Duration");


                //convert date to java date object
                java.util.Date jStartDate = new java.util.Date(startDate.getTime());

                //convert date object to calendar
                Calendar realStartDate = new GregorianCalendar();
                realStartDate.setTime(jStartDate);

                //get the days between the start of the plan and the first of this month
                //uses the joda time library
                planStartOffset = Days.daysBetween(new DateTime(past), new DateTime(realStartDate)).getDays();

                //set the offset of the end of plan
                planEndOffset = planStartOffset+duration-1;

                //if the start date exceeds the end of this month, or the end is before the first, just make a simple calendar
                if (planStartOffset >= lastOfMonth || planEndOffset<0)
                    simpleCalendar();

                //else continue making the calendar
                else
                {
                    //Now we need to get all the events that have been completed in the viewable timeframe
                    //lists of the different types of events
                    Vector<CompletedEvent> completedMetricEvents = new Vector<CompletedEvent>();
                    Vector<CompletedEvent> completedStaticEvents = new Vector<CompletedEvent>();
                    Vector<CompletedEvent> completedBpEvents = new Vector<CompletedEvent>();

                    //Make the lists using separate queries

                    //String to represent the first viewable date in MySQL format
                    String today = "'"+todaysYear+"-"+todaysMonth+"-"+todaysDOM+"'";
                    String lastViewableDay = "'"+todaysYear+"-"+todaysMonth+"-"+lastOfMonth+"'";

                    //metric first
                    PreparedStatement completedMetricEventsStatement = con.prepareStatement("SELECT E.Name,M.RecordedValue,DATE(DateTime) AS DateTime FROM events E, metric_data M WHERE PlanId = ? AND E.EventId=M.EventId AND DATE(DateTime) <= ? AND DATE(DateTime)>=? AND M.UserId=?");
                    completedMetricEventsStatement.setInt(1,planId);
                    completedMetricEventsStatement.setString(2,today);
                    completedMetricEventsStatement.setString(3,lastViewableDay);
                    completedMetricEventsStatement.setInt(4,userId);
                    ResultSet completedMetricEventsRs = completedMetricEventsStatement.executeQuery();

                    //convert result set of query into list of completed metric events
                    while(completedMetricEventsRs.next())
                    {
                        System.out.print("before first loop");
                        CompletedEvent temp = new CompletedEvent();
                        temp.setEventName(completedMetricEventsRs.getString("Name"));
                        int recordedValue = completedMetricEventsRs.getInt("RecordedValue");
                        if (recordedValue<0)
                            temp.setCompleted(-1);
                        else
                            temp.setCompleted(1);

                        java.sql.Date eventDate = completedMetricEventsRs.getDate("DateTime");
                        java.util.Date jeventDate = new java.util.Date(eventDate.getTime());
                        Calendar realEventDate = new GregorianCalendar();
                        realEventDate.setTime(jeventDate);

                        //get the offset between the first and the event (add 1 to get a day of month)
                        int offset = Days.daysBetween(new DateTime(past), new DateTime(realEventDate)).getDays();
                        temp.setDate(offset+1);

                        //add this event object to the list of metric events
                        completedMetricEvents.add(temp);
                        System.out.print("after first loop");
                    }

                    //static events next
                    PreparedStatement completedStaticEventsStatement = con.prepareStatement("SELECT E.Name,S.Completed,DATE(DateTime) AS DateTime FROM events E, static_data S WHERE PlanId = ? AND E.EventId=S.EventId AND DATE(DateTime) <= ? AND DATE(DateTime)>=? AND S.UserId=?");
                    completedStaticEventsStatement.setInt(1,planId);
                    completedStaticEventsStatement.setString(2,today);
                    completedStaticEventsStatement.setString(3,lastViewableDay);
                    completedStaticEventsStatement.setInt(4,userId);
                    ResultSet completedStaticEventsRs = completedStaticEventsStatement.executeQuery();

                    //convert result set of query into list of completed static events
                    while(completedStaticEventsRs.next())
                    {
                        CompletedEvent temp = new CompletedEvent();
                        temp.setEventName(completedStaticEventsRs.getString("Name"));
                        int completed = completedStaticEventsRs.getInt("Completed");
                        if (completed>0)
                            temp.setCompleted(1);
                        else
                            temp.setCompleted(-1);

                        java.sql.Date eventDate = completedStaticEventsRs.getDate("DateTime");
                        java.util.Date jeventDate = new java.util.Date(eventDate.getTime());
                        Calendar realEventDate = new GregorianCalendar();
                        realEventDate.setTime(jeventDate);

                        //get the offset between the first and the event (add 1 to get a day of month)
                        int offset = Days.daysBetween(new DateTime(past), new DateTime(realEventDate)).getDays();
                        temp.setDate(offset+1);

                        //add this event object to the list of metric events
                        completedStaticEvents.add(temp);
                    }
                    System.out.print("after second loop");

                    //bp events next
                    PreparedStatement completedBpEventsStatement = con.prepareStatement("SELECT E.Name,B.Systolic,DATE(DateTime) FROM events E, bp_data B WHERE PlanId = ? AND E.EventId=B.EventId AND DATE(DateTime) <= ? AND DATE(DateTime)>=? AND B.UserId=?");
                    completedBpEventsStatement.setInt(1,planId);
                    completedBpEventsStatement.setString(2,today);
                    completedBpEventsStatement.setString(3,lastViewableDay);
                    completedBpEventsStatement.setInt(4,userId);
                    ResultSet completedBpEventsRs = completedBpEventsStatement.executeQuery();

                    //convert result set of query into list of completed bp events
                    while(completedBpEventsRs.next())
                    {
                        CompletedEvent temp = new CompletedEvent();
                        temp.setEventName(completedBpEventsRs.getString("Name"));
                        int systolic = completedBpEventsRs.getInt("Systolic");
                        if (systolic<0)
                            temp.setCompleted(-1);
                        else
                            temp.setCompleted(1);

                        java.sql.Date eventDate = completedBpEventsRs.getDate("DateTime");
                        java.util.Date jeventDate = new java.util.Date(eventDate.getTime());
                        Calendar realEventDate = new GregorianCalendar();
                        realEventDate.setTime(jeventDate);

                        //get the offset between the first and the event (add 1 to get a day of month)
                        int offset = Days.daysBetween(new DateTime(past), new DateTime(realEventDate)).getDays();
                        temp.setDate(offset+1);

                        //add this event object to the list of metric events
                        completedBpEvents.add(temp);
                    }
                    System.out.print("after second loop");

                    //now we need to convert all this data into an array of Day objects
                    //which can be more easily used to make the json object to return

                    //a list of day objects to represent days
                    //on a 42 day calendar
                    Vector<Day> calendar = new Vector<Day>();

                    //counter to keep track of the actual days of the month
                    int dayCounter = 1;

                    //fill up the list appropriately
                    for (int i=1; i<43; i++)
                    {
                        System.out.println(i);
                        //a single day object
                        Day tempDay;

                        //make sure to only fill out those days
                        //that will actually have dates
                        if(i<firstOfMonthDOW || i>(lastOfMonth+firstOfMonthDOW-1))
                            tempDay = new Day(-1,null);
                        else
                        {
                            //construct the list of events that will go in the day object
                            Vector<CompletedEvent> tempEventList = new Vector<CompletedEvent>();

                            //use the list of completed events to construct the events list
                            //completed metric events
                            for(int j=0;j<completedMetricEvents.size(); j++)
                            {
                                if(completedMetricEvents.get(j).getDate()==dayCounter)
                                {
                                    CompletedEvent tempEvent = new CompletedEvent();
                                    tempEvent.setEventName(completedMetricEvents.get(j).getEventName());
                                    tempEvent.setEventType("metric");
                                    tempEvent.setCompleted(completedMetricEvents.get(j).getCompleted());
                                    tempEvent.setDate(dayCounter);
                                    tempEventList.add(tempEvent);
                                }
                            }

                            //completed static events
                            for(int j=0;j<completedStaticEvents.size(); j++)
                            {
                                if(completedStaticEvents.get(j).getDate()==dayCounter)
                                {
                                    CompletedEvent tempEvent = new CompletedEvent();
                                    tempEvent.setEventName(completedStaticEvents.get(j).getEventName());
                                    tempEvent.setEventType("static");
                                    tempEvent.setCompleted(completedStaticEvents.get(j).getCompleted());
                                    tempEvent.setDate(dayCounter);
                                    tempEventList.add(tempEvent);
                                }
                            }

                            //completed bp events
                            for(int j=0;j<completedBpEvents.size(); j++)
                            {
                                if(completedBpEvents.get(j).getDate()==dayCounter)
                                {
                                    CompletedEvent tempEvent = new CompletedEvent();
                                    tempEvent.setEventName(completedBpEvents.get(j).getEventName());
                                    tempEvent.setEventType("bp");
                                    tempEvent.setCompleted(completedBpEvents.get(j).getCompleted());
                                    tempEvent.setDate(dayCounter);
                                    tempEventList.add(tempEvent);
                                }
                            }

                            //now add the rest of the information for the day
                            tempDay = new Day(dayCounter,tempEventList);
                            dayCounter++;
                        }

                        calendar.add(tempDay);
                    }

                    //call the method to turn the list into a JSON object
                    makeJsonObject(calendar);
                }         
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                try{
                    con.close();
                }catch(Exception e){

                }
            }


        }
    }
    
    private void makeJsonObject(Vector<Day> daysList)
    {
        //the json object to return to the calling page
        String jsonObject = "{";
        int dayNumber;
        Vector<CompletedEvent> tempEventList;
        
        //add the name of the month and year and text for days array
        jsonObject+="\"year\" : \"" + todaysYear + "\",\n\"month\" : \"" + months[todaysMonth-1] + "\",\n\"days\" : [\n";
        
        //go through the days list and generate each json array item
        for(int i=0;i<daysList.size();i++)
        {
            dayNumber = daysList.get(i).getDayNumber();
            tempEventList = daysList.get(i).getEventList();
            
            jsonObject+="{\"dayNum\" : \"";
            if (dayNumber<0)
                jsonObject+="\",\n\"eventList\" : [\n";
            else
                jsonObject+=dayNumber+"\",\n\"eventList\" : [\n";
            
            if(tempEventList != null)
            {
                //go through each days event list
                for (int j=0;j<tempEventList.size();j++)
                {
                    CompletedEvent tempEvent = tempEventList.get(j);
                    jsonObject+="{\"eventName\" : \""+tempEvent.getEventName()+"\",\n\"eventType\" : \""+tempEvent.getEventType()+"\",\n";
                    jsonObject+="\"completed\" : \""+tempEvent.getCompleted()+"\"}";

                    if(j<tempEventList.size()-1)
                        jsonObject+=",";
                }
            }
            
            jsonObject+="\n]\n}";
            
            if(i<daysList.size()-1)
                jsonObject+=",";
        }
        
        jsonObject+="]}";
        out.print(jsonObject);
    
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
